package com.icongyou.enterprise.talent_pool.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.util.*;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class AIModelServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @Mock
    private ObjectMapper objectMapper;

    @InjectMocks
    private AIModelService aiModelService;

    private final String testApiUrl = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation";
    private final String testApiKey = "test-api-key";
    private final String testModel = "qwen-max";

    @BeforeEach
    void setUp() throws Exception {
        // 使用反射设置私有字段的值
        var field = aiModelService.getClass().getDeclaredField("aiModelApiUrl");
        field.setAccessible(true);
        field.set(aiModelService, testApiUrl);

        field = aiModelService.getClass().getDeclaredField("aiModelApiKey");
        field.setAccessible(true);
        field.set(aiModelService, testApiKey);

        field = aiModelService.getClass().getDeclaredField("aiModel");
        field.setAccessible(true);
        field.set(aiModelService, testModel);
    }

    @Test
    void testCallAIModelAPI_Success() {
        // 准备测试数据
        Map<String, Object> request = new HashMap<>();
        request.put("test", "data");

        Map<String, Object> expectedResponse = new HashMap<>();
        expectedResponse.put("output", Map.of("text", "test response"));

        // 模拟行为
        when(restTemplate.postForObject(eq(testApiUrl), any(HttpEntity.class), eq(Map.class)))
                .thenReturn(expectedResponse);

        // 执行测试
        Map<String, Object> actualResponse = aiModelService.callAIModelAPI(request);

        // 验证结果
        assertNotNull(actualResponse);
        assertEquals(expectedResponse, actualResponse);
        verify(restTemplate).postForObject(eq(testApiUrl), any(HttpEntity.class), eq(Map.class));
    }

    @Test
    void testCallAIModelAPI_Exception() {
        // 准备测试数据
        Map<String, Object> request = new HashMap<>();
        request.put("test", "data");

        // 模拟行为 - 抛出异常
        when(restTemplate.postForObject(eq(testApiUrl), any(HttpEntity.class), eq(Map.class)))
                .thenThrow(new RuntimeException("API call failed"));

        // 执行测试并验证异常
        RuntimeException exception = assertThrows(RuntimeException.class,
                () -> aiModelService.callAIModelAPI(request));

        assertTrue(exception.getMessage().contains("大模型API调用失败"));
    }

    @Test
    void testBuildAIModelRequest() {
        // 准备测试数据
        String prompt = "测试提示词";

        // 执行测试
        Map<String, Object> request = aiModelService.buildAIModelRequest(prompt);

        // 验证结果
        assertNotNull(request);
        assertEquals(testModel, request.get("model"));

        @SuppressWarnings("unchecked")
        Map<String, Object> input = (Map<String, Object>) request.get("input");
        assertNotNull(input);

        @SuppressWarnings("unchecked")
        List<Map<String, String>> messages = (List<Map<String, String>>) input.get("messages");
        assertEquals(2, messages.size());
        assertEquals("user", messages.get(1).get("role"));
        assertEquals(prompt, messages.get(1).get("content"));

        @SuppressWarnings("unchecked")
        Map<String, Object> parameters = (Map<String, Object>) request.get("parameters");
        assertEquals(0.3, parameters.get("temperature"));
        assertEquals(2000, parameters.get("max_tokens"));
    }

    @Test
    void testAnalyzeAssignmentTags_Success() throws Exception {
        // 准备测试数据
        String assignmentDescription = "开发一个基于机器学习的推荐系统";

        // 创建更真实的API响应结构
        Map<String, Object> apiResponse = new HashMap<>();
        Map<String, Object> output = new HashMap<>();
        String jsonContent = "{\"tags\": [{\"tagName\": \"机器学习\", \"relevance\": 0.9, \"similarTags\": [\"ML\", \"Machine Learning\"]}]}";
        output.put("text", jsonContent);
        apiResponse.put("output", output);

        // 模拟行为
        when(restTemplate.postForObject(anyString(), any(HttpEntity.class), eq(Map.class)))
                .thenReturn(apiResponse);

        // 模拟ObjectMapper的行为
        Map<String, Object> parsedResult = new HashMap<>();
        List<Map<String, Object>> tags = new ArrayList<>();
        Map<String, Object> tag = new HashMap<>();
        tag.put("tagName", "机器学习");
        tag.put("relevance", 0.9);
        tag.put("similarTags", Arrays.asList("ML", "Machine Learning"));
        tags.add(tag);
        parsedResult.put("tags", tags);

        when(objectMapper.readValue(anyString(), eq(Map.class))).thenReturn(parsedResult);

        // 执行测试
        List<TagAnalysisResult> results = aiModelService.analyzeAssignmentTags(assignmentDescription);

        // 验证结果
        assertNotNull(results);
        assertFalse(results.isEmpty());
        assertEquals("机器学习", results.get(0).getTagName());
        assertEquals(0.9, results.get(0).getRelevance());
        assertEquals(Arrays.asList("ML", "Machine Learning"), results.get(0).getSimilarTags());
    }

    @Test
    void testAnalyzeAssignmentTags_Fallback() {
        // 准备测试数据
        String assignmentDescription = "开发一个Java web应用";

        // 模拟行为 - API调用失败
        when(restTemplate.postForObject(anyString(), any(HttpEntity.class), eq(Map.class)))
                .thenThrow(new RuntimeException("API call failed"));

        // 执行测试
        List<TagAnalysisResult> results = aiModelService.analyzeAssignmentTags(assignmentDescription);

        // 验证结果 - 应该使用降级方案
        assertNotNull(results);
        assertFalse(results.isEmpty());
        // 因为描述包含"Java"，所以应该返回Java标签
        assertEquals("Java", results.get(0).getTagName());
        assertEquals(0.7, results.get(0).getRelevance());
    }

    @Test
    void testAnalyzeDemandTags_Success() throws Exception {
        // 准备测试数据
        String demandText = "需要熟悉Python和数据分析的人才";

        // 创建更真实的API响应结构
        Map<String, Object> apiResponse = new HashMap<>();
        Map<String, Object> output = new HashMap<>();
        String jsonContent = "{\"tags\": [{\"tagName\": \"Python\", \"similarTags\": [\"Python编程\"]}]}";
        output.put("text", jsonContent);
        apiResponse.put("output", output);

        // 模拟行为
        when(restTemplate.postForObject(anyString(), any(HttpEntity.class), eq(Map.class)))
                .thenReturn(apiResponse);

        // 模拟ObjectMapper的行为
        Map<String, Object> parsedResult = new HashMap<>();
        List<Map<String, Object>> tags = new ArrayList<>();
        Map<String, Object> tag = new HashMap<>();
        tag.put("tagName", "Python");
        tag.put("similarTags", Arrays.asList("Python编程"));
        tags.add(tag);
        parsedResult.put("tags", tags);

        when(objectMapper.readValue(anyString(), eq(Map.class))).thenReturn(parsedResult);

        // 执行测试
        List<TagDemandAnalysisResult> results = aiModelService.analyzeDemandTags(demandText);

        // 验证结果
        assertNotNull(results);
        assertFalse(results.isEmpty());
        assertEquals("Python", results.get(0).getTagName());
        assertEquals(Arrays.asList("Python编程"), results.get(0).getSimilarTags());
    }

    @Test
    void testAnalyzeDemandTags_Fallback() {
        // 准备测试数据
        String demandText = "需要前端开发工程师";

        // 模拟行为 - API调用失败
        when(restTemplate.postForObject(anyString(), any(HttpEntity.class), eq(Map.class)))
                .thenThrow(new RuntimeException("API call failed"));

        // 执行测试
        List<TagDemandAnalysisResult> results = aiModelService.analyzeDemandTags(demandText);

        // 验证结果 - 应该使用降级方案
        assertNotNull(results);
        assertFalse(results.isEmpty());
        assertEquals("前端", results.get(0).getTagName());
    }

    @Test
    void testBatchCalculateTagRelevance_Success() throws Exception {
        // 准备测试数据
        String tagName = "机器学习";
        Map<String, String> assignmentDescriptions = new HashMap<>();
        assignmentDescriptions.put("task1", "开发机器学习模型");
        assignmentDescriptions.put("task2", "前端页面开发");
        assignmentDescriptions.put("task3", "数据分析和处理");

        // 创建更真实的API响应结构
        Map<String, Object> apiResponse = new HashMap<>();
        Map<String, Object> output = new HashMap<>();
        String jsonContent = "{\"relevant_assignments\": {\"task1\": 0.8, \"task3\": 0.6}}";
        output.put("text", jsonContent);
        apiResponse.put("output", output);

        // 模拟行为
        when(restTemplate.postForObject(anyString(), any(HttpEntity.class), eq(Map.class)))
                .thenReturn(apiResponse);

        // 模拟ObjectMapper的行为
        Map<String, Object> parsedResult = new HashMap<>();
        Map<String, Object> relevantAssignments = new HashMap<>();
        relevantAssignments.put("task1", 0.8);
        relevantAssignments.put("task3", 0.6);
        parsedResult.put("relevant_assignments", relevantAssignments);

        when(objectMapper.readValue(anyString(), eq(Map.class))).thenReturn(parsedResult);

        // 执行测试
        Map<String, Double> results = aiModelService.batchCalculateTagRelevance(tagName, assignmentDescriptions);

        // 验证结果
        assertNotNull(results);
        assertEquals(2, results.size());
        assertEquals(0.8, results.get("task1"));
        assertEquals(0.6, results.get("task3"));
        assertNull(results.get("task2")); // task2关联度应该为0或不存在
    }

    @Test
    void testBatchCalculateTagRelevance_EmptyResult() {
        // 准备测试数据
        String tagName = "区块链";
        Map<String, String> assignmentDescriptions = new HashMap<>();
        assignmentDescriptions.put("task1", "前端开发");
        assignmentDescriptions.put("task2", "后端开发");

        // 模拟行为 - API调用失败
        when(restTemplate.postForObject(anyString(), any(HttpEntity.class), eq(Map.class)))
                .thenThrow(new RuntimeException("API call failed"));

        // 执行测试
        Map<String, Double> results = aiModelService.batchCalculateTagRelevance(tagName, assignmentDescriptions);

        // 验证结果 - 应该返回空Map
        assertNotNull(results);
        assertTrue(results.isEmpty());
    }

    @Test
    void testParseAssignmentTagResponse_WithErrorCode() {
        // 准备测试数据 - 包含错误码的响应
        Map<String, Object> response = new HashMap<>();
        response.put("code", "error_code");

        // 使用反射调用私有方法
        List<TagAnalysisResult> results = invokePrivateParseAssignmentTagResponse(response);

        // 验证结果
        assertNotNull(results);
        assertTrue(results.isEmpty());
    }

    @Test
    void testParseAssignmentTagResponse_EmptyOutput() {
        // 准备测试数据 - 空输出
        Map<String, Object> response = new HashMap<>();
        response.put("output", null);

        // 使用反射调用私有方法
        List<TagAnalysisResult> results = invokePrivateParseAssignmentTagResponse(response);

        // 验证结果
        assertNotNull(results);
        assertTrue(results.isEmpty());
    }

    @Test
    void testParseAssignmentTagResponse_EmptyText() {
        // 准备测试数据 - 空文本
        Map<String, Object> response = new HashMap<>();
        Map<String, Object> output = new HashMap<>();
        output.put("text", "");
        response.put("output", output);

        // 使用反射调用私有方法
        List<TagAnalysisResult> results = invokePrivateParseAssignmentTagResponse(response);

        // 验证结果
        assertNotNull(results);
        assertTrue(results.isEmpty());
    }

    // 辅助方法：通过反射调用私有方法
    @SuppressWarnings("unchecked")
    private List<TagAnalysisResult> invokePrivateParseAssignmentTagResponse(Map<String, Object> response) {
        try {
            var method = aiModelService.getClass().getDeclaredMethod("parseAssignmentTagResponse", Map.class);
            method.setAccessible(true);
            return (List<TagAnalysisResult>) method.invoke(aiModelService, response);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}